import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:ideology/features/screens/code_editor_controller.dart';
import 'package:ideology/features/screens/widgets/editor_menu_bar/dialogs/new_project_dialog/new_project_dialog.dart';
import 'package:ideology/shared/widgets/code_input/highlight/languages/cloudish.dart';
import 'package:ideology/shared/widgets/code_input/highlight/languages/dartish.dart';
import 'package:ideology/shared/widgets/code_input/highlight/languages/javaish.dart';
import 'package:ideology/shared/widgets/code_input/highlight/languages/plain.dart';
import 'package:ideology/shared/widgets/code_input/highlight/languages/snow.dart';
import 'package:ideology/shared/widgets/file_explorer/file_node.dart';
import 'package:path/path.dart' as p;
import 'package:shared_preferences/shared_preferences.dart';

/// 单次运行/调试的结果封装
class _RunResult {
  final int exitCode; // 进程退出码
  final String tail;  // 日志最后 N 行（环形缓冲区保存）
  _RunResult(this.exitCode, this.tail);
}

/// 编辑器的业务用例入口
/// - 主要职责是编排 **CodeEditorController**
/// - 对外提供统一 API，例如：新建/打开/关闭项目、运行项目等
class CodeEditorUseCases {
  final CodeEditorController controller;

  CodeEditorUseCases({required this.controller});

  /// 新建项目（包装 controller 的 createNewProjectWith）
  Future<void> newProjectWith(NewProjectData data) =>
      controller.createNewProjectWith(data);

  /// 打开已有项目
  Future<void> openProject() => controller.pickAndLoadProject();

  /// 关闭当前项目
  void closeProject() => controller.closeCurrentProject();

  /// 切换文件资源管理器可见性
  void toggleExplorer() => controller.toggleExplorer();

  /// 切换输出面板可见性
  void toggleOutput() => controller.toggleOutput();

  /// 设置当前选中的路径
  void selectPath(String path) => controller.setSelectedPath(path);

  /// 打开指定文件节点
  Future<void> openNode(String path, FileNode node) =>
      controller.openFile(path, node);

  Future<void> dispose() async {}

  /// 编译并运行项目（调用 `snow compile run`）
  Future<void> runProject() async {
    final exePath = await _prepareSnowExecutable();
    final projectRoot = controller.projectRootPath!;

    controller.showOutput.value = true;
    controller.clearOutput();

    if (kDebugMode) {
      _debugPrint('Running: $exePath compile run');
      _debugPrint('Working directory: $projectRoot');
    }

    final res = await _runAndPipeLogs(
      exePath: exePath,
      args: const ['compile', 'run'],
      workingDirectory: projectRoot,
    );

    if (res.exitCode != 0) {
      _emit('\nCompile/Run failed (exit code ${res.exitCode})');
      return;
    }

    _emit('Run completed (exit code 0)');
  }

  /// 调试模式运行项目（调用 `snow compile run --debug`）
  Future<void> debugProject() async {
    final exePath = await _prepareSnowExecutable();
    final projectRoot = controller.projectRootPath!;

    controller.showOutput.value = true;
    controller.clearOutput();

    if (kDebugMode) {
      _debugPrint('Debug:   $exePath compile run --debug');
      _debugPrint('Working directory: $projectRoot');
    }

    final res = await _runAndPipeLogs(
      exePath: exePath,
      args: const ['compile', 'run', '--debug'],
      workingDirectory: projectRoot,
    );

    if (res.exitCode != 0) {
      _emit('\nDebug run failed (exit code ${res.exitCode})');
      return;
    }

    _emit('\nDebug run completed (exit code 0)');
  }

  /// 启动外部进程，并把 stdout/stderr 实时转发到输出面板
  Future<_RunResult> _runAndPipeLogs({
    required String exePath,
    required List<String> args,
    required String workingDirectory,
  }) async {
    final process = await Process.start(
      exePath,
      args,
      workingDirectory: workingDirectory,
      runInShell: false,
    );

    final ring = _RingBuffer(maxLines: 80); // 保存最近 80 行日志

    final stdoutDone = Completer<void>();
    final stderrDone = Completer<void>();

    // 监听 stdout
    process.stdout.transform(const Utf8Decoder()).listen((chunk) {
      _emit(chunk);
      ring.addChunk(chunk);
    }, onDone: () => stdoutDone.complete());

    // 监听 stderr
    process.stderr.transform(const Utf8Decoder()).listen((chunk) {
      _emit(chunk, isError: true);
      ring.addChunk(chunk);
    }, onDone: () => stderrDone.complete());

    final code = await process.exitCode;
    await Future.wait([stdoutDone.future, stderrDone.future]);

    return _RunResult(code, ring.dump());
  }

  /// 检查项目与 SDK 配置，返回 Snow 可执行文件路径
  Future<String> _prepareSnowExecutable() async {
    final projectRoot = controller.projectRootPath;
    if (projectRoot == null || projectRoot.isEmpty) {
      _emit('No project is open, unable to run', isError: true);
      throw StateError('No project open');
    }

    const sdkCurrentKey = 'sdk_current_path';
    final prefs = await SharedPreferences.getInstance();
    final sdkPath = prefs.getString(sdkCurrentKey);
    if (sdkPath == null || sdkPath.isEmpty) {
      _emit('No SDK selected in Settings', isError: true);
      throw StateError('No SDK selected');
    }

    // 根据系统选择可执行文件名
    final exeName = Platform.isWindows ? 'Snow.exe' : 'snow';
    final exePath = p.join(sdkPath, 'bin', exeName);

    final exists = await File(exePath).exists();
    if (!exists) {
      _emit('Snow executable not found at $exePath', isError: true);
      throw StateError('Snow executable not found');
    }

    return exePath;
  }

  /// 写日志到输出面板，同时调试模式下写入 stdout/stderr
  void _emit(String s, {bool isError = false}) {
    controller.appendOutput(s);

    if (kDebugMode) {
      if (isError) {
        stderr.write(s);
      } else {
        stdout.write(s);
      }
    }
  }

  void _debugPrint(String s) {
    if (kDebugMode) {
      print(s);
    }
  }
}

/// 简单环形缓冲区：保存日志的最后 [maxLines] 行
class _RingBuffer {
  _RingBuffer({required this.maxLines});

  final int maxLines;
  final List<String> _lines = [];
  String _carry = ''; // 临时拼接一行未完成日志

  /// 添加一段日志，按行分割并保存
  void addChunk(String chunk) {
    final normalized =
    chunk.replaceAll('\r\n', '\n').replaceAll('\r', '\n');

    final parts = normalized.split('\n');
    _carry += parts.first;

    for (var i = 1; i < parts.length; i++) {
      _push(_carry);
      _carry = parts[i];
    }
  }

  /// 存入一行，并维护长度不超过 maxLines
  void _push(String line) {
    _lines.add(line);
    if (_lines.length > maxLines) _lines.removeAt(0);
  }

  /// 导出当前保存的所有日志
  String dump() {
    if (_carry.isNotEmpty) {
      return [..._lines, _carry].join('\n');
    }
    return _lines.join('\n');
  }
}

/// 文件语言枚举，用于选择语法高亮方案
enum FileLang { dart, java, snow, plain, cloud }

/// 根据文件名后缀推断语言类型
FileLang guessFileLang(String filename) {
  final lower = filename.toLowerCase();
  if (lower.endsWith('.dart')) return FileLang.dart;
  if (lower.endsWith('.java')) return FileLang.java;
  if (lower.endsWith('.snow')) return FileLang.snow;
  if (lower.endsWith('.cloud')) return FileLang.cloud;
  return FileLang.plain;
}

/// 根据文件名返回对应的语法高亮 preset
dynamic makePresetForFilename(String filename, TextStyle base) {
  switch (guessFileLang(filename)) {
    case FileLang.dart:
      return makeDartishPreset(base);
    case FileLang.java:
      return makeJavaishPreset(base);
    case FileLang.snow:
      return makeSnowPreset(base);
    case FileLang.plain:
      return makePlainPreset(base);
    case FileLang.cloud:
      return makeCloudPreset(base);
  }
}
